/**
 * Validator Manager
 * Centralized management of all configuration validators
 */

const ConfigValidator = require('./config-validator');
const ProviderValidator = require('./provider-validator');

class ValidatorManager {
  constructor() {
    this.validators = new Map();
    this.registerDefaults();
  }

  /**
   * Register default validators
   */
  registerDefaults() {
    this.register('config', new ConfigValidator());
    this.register('provider', new ProviderValidator());
  }

  /**
   * Register a validator
   * @param {string} name - Validator name
   * @param {BaseValidator} validator - Validator instance
   */
  register(name, validator) {
    if (!validator || typeof validator.validate !== 'function') {
      throw new Error(`Validator must implement validate method: ${name}`);
    }
    this.validators.set(name, validator);
  }

  /**
   * Get a validator by name
   * @param {string} name - Validator name
   * @returns {BaseValidator|null} Validator instance
   */
  getValidator(name) {
    return this.validators.get(name) || null;
  }

  /**
   * Get all registered validator names
   * @returns {Array<string>} Validator names
   */
  getValidatorNames() {
    return Array.from(this.validators.keys());
  }

  /**
   * Validate data using a specific validator
   * @param {string} validatorName - Validator name
   * @param {*} data - Data to validate
   * @param {Object} options - Validation options
   * @returns {Object} Validation result
   */
  validate(validatorName, data, options = {}) {
    const validator = this.getValidator(validatorName);
    if (!validator) {
      return {
        success: false,
        error: `Validator '${validatorName}' not found`,
        errors: [`Available validators: ${this.getValidatorNames().join(', ')}`]
      };
    }

    // For test mode, we need to create a new validator instance with the correct options
    if (options.testMode && ['config', 'provider'].includes(validatorName)) {
      const ValidatorClass = validator.constructor;
      const testValidator = new ValidatorClass(options);
      return testValidator.validate(data, options);
    }

    // Apply options to validator if supported
    if (options.testMode && validator.options) {
      validator.options.testMode = true;
    }

    return validator.validate(data, options);
  }

  /**
   * Validate configuration using the main config validator
   * @param {Object} config - Configuration to validate
   * @param {Object} options - Validation options
   * @returns {Object} Validation result
   */
  validateConfig(config, options = {}) {
    return this.validate('config', config, options);
  }

  /**
   * Validate provider configuration
   * @param {Object} provider - Provider configuration
   * @param {Object} options - Validation options
   * @returns {Object} Validation result
   */
  validateProvider(provider, options = {}) {
    return this.validate('provider', provider, options);
  }

  /**
   * Create test configuration for a validator
   * @param {string} validatorName - Validator name
   * @param {Object} overrides - Configuration overrides
   * @returns {Object|null} Test configuration
   */
  createTestConfig(validatorName, overrides = {}) {
    const validator = this.getValidator(validatorName);
    if (!validator || typeof validator.createTestConfig !== 'function') {
      return null;
    }

    return validator.createTestConfig(overrides);
  }

  /**
   * Validate configuration for testing purposes
   * @param {Object} config - Configuration to validate
   * @param {Object} options - Validation options
   * @returns {Object} Test validation result
   */
  validateForTest(config, options = {}) {
    return this.validateConfig(config, {
      testMode: true,
      strict: false,
      allowExtraFields: true,
      ...options
    });
  }

  /**
   * Get singleton instance
   * @returns {ValidatorManager} Manager instance
   */
  static getInstance() {
    if (!ValidatorManager.instance) {
      ValidatorManager.instance = new ValidatorManager();
    }
    return ValidatorManager.instance;
  }

  /**
   * Reset singleton instance (useful for testing)
   */
  static resetInstance() {
    ValidatorManager.instance = null;
  }
}

module.exports = ValidatorManager;